Skip to content

chore: api http router improvements#38227

Merged
kodiakhq[bot] merged 9 commits intodevelopfrom
chore/router-improvements
Feb 6, 2026
Merged

chore: api http router improvements#38227
kodiakhq[bot] merged 9 commits intodevelopfrom
chore/router-improvements

Conversation

@d-gubert
Copy link
Member

@d-gubert d-gubert commented Jan 17, 2026

Proposed changes (including videos or screenshots)

  • Remove duplicated calls to parseBodyParams and parseQueryParams in RocketChatAPIRouter
  • Prevent logger middleware from consuming the request body and trying to parse it to JSON when the env var is not set
  • Redact the password field when logging requests' payloads

Issue(s)

Steps to test or reproduce

Further comments

Summary by CodeRabbit

  • Security

    • Password and sensitive fields in API requests are now automatically redacted from logs.
  • Refactor

    • Logging now captures JSON request bodies and denotes multipart/form-data payloads when present.
    • Request body and query parsing are centralized and exposed on the request context; route and incoming request info are now included.
  • Bug Fixes

    • Removed a pre-validation check that could cause premature validation failures for certain IDs.

@dionisio-bot
Copy link
Contributor

dionisio-bot bot commented Jan 17, 2026

Looks like this PR is not ready to merge, because of the following issues:

  • This PR is targeting the wrong base branch. It should target 8.2.0, but it targets 8.1.0

Please fix the issues and try again

If you have any trouble, please check the PR guidelines

@changeset-bot
Copy link

changeset-bot bot commented Jan 17, 2026

⚠️ No Changeset found

Latest commit: 6ceaac9

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 17, 2026

Walkthrough

Request parsing now populates queryParams and bodyParams on the Hono context; log payload extraction is async and request-aware via getRestPayload; router and router-internal types expanded; customField ID pre-check removed (validation order changed).

Changes

Cohort / File(s) Summary
Logger middleware
apps/meteor/app/api/server/middlewares/logger.ts
Removed precomputed payload extraction and multipart handling; constructs log payload inline by awaiting getRestPayload(c.req) and uses logger.child(..., { redact: ['payload.password'] }). Public middleware signature unchanged.
Log payload extraction
apps/meteor/server/lib/logger/logPayloads.ts
getRestPayload is now async and accepts a HonoRequest; detects multipart/form-data (returns "[multipart/form-data]"), attempts request.raw.clone().json() for JSON bodies, returns { payload } or null; when disabled returns Promise<null>. Added import type { HonoRequest } from 'hono';.
Router & HTTP parsing
apps/meteor/app/api/server/router.ts, packages/http-router/src/Router.ts
Hono context gains queryParams and bodyParams fields; APIActionContext now includes route and incoming. Introduced InnerRouter type; parseBodyParams refactored to async, parses JSON and application/x-www-form-urlencoded, stores parsed values via c.set('queryParams', ...) and c.set('bodyParams', ...). getHonoRouter and innerRouter types updated accordingly.
Livechat custom field validation
apps/meteor/app/livechat/server/api/v1/customField.ts
Removed early regex pre-condition for customFieldId; validation/order changed so existence/duplication checks remain but the prior immediate regex fail is no longer performed.

Sequence Diagram(s)

sequenceDiagram
    participant Client as Client
    participant Router as Router (Hono)
    participant Parser as parseBodyParams
    participant LoggerMW as Logger Middleware
    participant LogPayload as getRestPayload
    participant Handler as API Handler

    Client->>Router: HTTP request
    Router->>Parser: parse query/body -> c.set('queryParams','bodyParams')
    Router->>LoggerMW: invoke middleware with context
    LoggerMW->>LogPayload: await getRestPayload(c.req)
    LogPayload-->>LoggerMW: payload or null
    LoggerMW-->>Router: continue to handler
    Router->>Handler: construct APIActionContext (route, incoming, queryParams, bodyParams)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 I hop through contexts, light and spry,
I tuck the params where they lie,
I fetch a payload, soft and neat,
I whisper logs without a beat,
Tiny paws, big code delight ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'chore: api http router improvements' is vague and generic, lacking specificity about the actual changes made to the router. Consider a more specific title that highlights the main change, such as 'chore: consolidate http router payload parsing and improve logging' or similar.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chore/router-improvements

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@d-gubert d-gubert force-pushed the chore/router-improvements branch from 12a4f8f to b1b33d3 Compare January 17, 2026 00:19
@codecov
Copy link

codecov bot commented Jan 17, 2026

Codecov Report

❌ Patch coverage is 75.00000% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 70.38%. Comparing base (3ff4730) to head (6ceaac9).
⚠️ Report is 1 commits behind head on develop.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop   #38227      +/-   ##
===========================================
- Coverage    70.41%   70.38%   -0.03%     
===========================================
  Files         3161     3161              
  Lines       110653   110650       -3     
  Branches     19827    19866      +39     
===========================================
- Hits         77911    77881      -30     
- Misses       30719    30741      +22     
- Partials      2023     2028       +5     
Flag Coverage Δ
e2e 60.36% <ø> (-0.04%) ⬇️
e2e-api 47.76% <16.66%> (-0.02%) ⬇️
unit 71.39% <100.00%> (-0.03%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@d-gubert d-gubert added this to the 8.1.0 milestone Jan 17, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Jan 17, 2026

📦 Docker Image Size Report

➡️ Changes

Service Current Baseline Change Percent
sum of all images 0B 0B 0B
account-service 0B 0B 0B
authorization-service 0B 0B 0B
ddp-streamer-service 0B 0B 0B
omnichannel-transcript-service 0B 0B 0B
presence-service 0B 0B 0B
queue-worker-service 0B 0B 0B
rocketchat 0B 0B 0B

📊 Historical Trend

---
config:
  theme: "dark"
  xyChart:
    width: 900
    height: 400
---
xychart
  title "Image Size Evolution by Service (Last 30 Days + This PR)"
  x-axis ["11/18 22:53", "11/19 23:02", "11/21 16:49", "11/24 17:34", "11/27 22:32", "11/28 19:05", "12/01 23:01", "12/02 21:57", "12/03 21:00", "12/04 18:17", "12/05 21:56", "12/08 20:15", "12/09 22:17", "12/10 23:26", "12/11 21:56", "12/12 22:45", "12/13 01:34", "12/15 22:31", "12/16 22:18", "12/17 21:04", "12/18 23:12", "12/19 23:27", "12/20 21:03", "12/22 18:54", "12/23 16:16", "12/24 19:38", "12/25 17:51", "12/26 13:18", "12/29 19:01", "12/30 20:52", "02/05 21:26 (PR)"]
  y-axis "Size (GB)" 0 --> 0.5
  line "account-service" [0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.00]
  line "authorization-service" [0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.00]
  line "ddp-streamer-service" [0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.00]
  line "omnichannel-transcript-service" [0.14, 0.14, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.00]
  line "presence-service" [0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.00]
  line "queue-worker-service" [0.14, 0.14, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.00]
  line "rocketchat" [0.35, 0.35, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.00]
Loading

Statistics (last 30 days):

  • 📊 Average: 1.5GiB
  • ⬇️ Minimum: 1.4GiB
  • ⬆️ Maximum: 1.6GiB
  • 🎯 Current PR: 0B
ℹ️ About this report

This report compares Docker image sizes from this build against the develop baseline.

  • Tag: pr-38227
  • Baseline: develop
  • Timestamp: 2026-02-05 21:26:34 UTC
  • Historical data points: 30

Updated: Thu, 05 Feb 2026 21:26:35 GMT

@d-gubert d-gubert force-pushed the chore/router-improvements branch from dd78dad to 536fd45 Compare January 20, 2026 23:28
@d-gubert
Copy link
Member Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 20, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/rest-typings/src/v1/omnichannel.ts (1)

4502-4505: Type guard does not match schema nullability for customFieldId.

The schema defines customFieldId with nullable: true and no required array (making it optional), but the type guard narrows to customFieldId: string. After validation, customFieldId could be null or omitted (undefined), violating the type guard. Align the generic type to customFieldId?: string | null to match the schema.

Suggested fix
 export const isPOSTLivechatSaveCustomFieldsParams = ajv.compile<{
-	customFieldId: string;
+	customFieldId?: string | null;
 	customFieldData: Omit<ILivechatCustomField, '_id' | '_updatedAt'> & { field: string };
 }>(POSTLivechatSaveCustomFieldsSchema);
🤖 Fix all issues with AI agents
In `@packages/rest-typings/src/v1/omnichannel.ts`:
- Around line 4446-4457: Update the regex character classes to move the hyphen
to the end so they read `[0-9a-zA-Z_-]` for both customFieldId and
customFieldData.field to avoid creating an unintended range; also reconcile the
nullable mismatch by either removing `nullable: true` from the `customFieldId`
schema or updating the type guard that references `customFieldId` (the check
near the type guard around line ~4502) to accept `string | null` so schema and
runtime types match.
🧹 Nitpick comments (1)
packages/http-router/src/Router.ts (1)

157-175: Align bodyParams typing with possible JSON shapes.
request.raw.clone().json() can return arrays or primitives, but the context types are Record<string, unknown>. Consider normalizing non‑object bodies to {} or widening the type so downstream code doesn’t rely on an incorrect shape.

@d-gubert d-gubert force-pushed the chore/router-improvements branch from 536fd45 to 2186968 Compare January 21, 2026 00:39
@d-gubert d-gubert marked this pull request as ready for review January 21, 2026 11:59
@d-gubert d-gubert requested review from a team as code owners January 21, 2026 11:59
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 9 files

@ggazzo ggazzo modified the milestones: 8.1.0, 8.2.0 Jan 21, 2026
@ricardogarim
Copy link
Contributor

ricardogarim commented Jan 21, 2026

While reviewing the bodyParams-override removal, which looks correct since parseBodyParams never used the extra parameter, I noticed that incoming webhooks receiving application/x-www-form-urlencoded with payload={...json...} (Slack/GitHub format) have been broken for a while. The JSON is never unwrapped from the payload field.

Created CORE-1741 to track this separately.

@sampaiodiego
Copy link
Member

@ricardogarim are they really broken? I've found this test to validate it (should) be working:

it('should send a message if the payload is a application/x-www-form-urlencoded JSON', async () => {
const payload = { msg: `Message as x-www-form-urlencoded JSON sent successfully at #${Date.now()}` };
await request
.post(`/hooks/${integration._id}/${integration.token}`)
.set('Content-Type', 'application/x-www-form-urlencoded')
.send(`payload=${JSON.stringify(payload)}`)
.expect(200)
.expect(async () => {
return request
.get(api('channels.messages'))
.set(credentials)
.query({
roomId: 'GENERAL',
})
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
expect(res.body).to.have.property('messages').and.to.be.an('array');
expect(!!(res.body.messages as IMessage[]).find((m) => m.msg === payload.msg)).to.be.true;
});
});
});

@sampaiodiego
Copy link
Member

@d-gubert maybe the Livechat changes could be in another PR? they look like regular changes not necessarily related to "api http router improments"

@d-gubert
Copy link
Member Author

d-gubert commented Jan 21, 2026

@d-gubert maybe the Livechat changes could be in another PR? they look like regular changes not necessarily related to "api http router improments"

We need to modify that endpoint, otherwise tests fail because of this #38227 (comment) (there was an example of CI run with the tests failing, but I rebased... 😬 ) (actually, found the run https://github.com/RocketChat/Rocket.Chat/actions/runs/21084954407/job/60650568531?pr=38227)

I can make a much more contrived change just to make sure the tests are passing, then open a new PR with the appropriate changes to schemas and all. But the endpoint can't go unscathed 😛

@d-gubert
Copy link
Member Author

Forgot to mention @sampaiodiego #38227 (comment) 😬

@d-gubert d-gubert force-pushed the chore/router-improvements branch from 2186968 to 5ffad11 Compare January 23, 2026 15:55
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/models/src/models/LivechatCustomField.ts (1)

52-75: Return value missing _id in update path.

When updating an existing record (_id is truthy), the returned record object lacks the _id property, which violates the ILivechatCustomField return type. The insert path correctly assigns record._id = field, but the update path does not preserve the ID on the returned object.

🐛 Proposed fix
 	async createOrUpdateCustomField(
 		_id: string | null,
 		field: string,
 		label: ILivechatCustomField['label'],
 		scope: ILivechatCustomField['scope'],
 		visibility: ILivechatCustomField['visibility'],
 		extraData: any,
 	) {
 		const record = {
 			label,
 			scope,
 			visibility,
 			...extraData,
 		};

 		if (_id) {
 			await this.updateOne({ _id }, { $set: record });
+			record._id = _id;
 		} else {
 			record._id = field;
 			await this.insertOne(record);
 		}

 		return record;
 	}
🤖 Fix all issues with AI agents
In `@apps/meteor/app/api/server/router.ts`:
- Around line 44-49: The APIActionContext construction should defensively
default potentially-undefined context entries; update the code that builds
APIActionContext (the object with requestIp, urlParams, queryParams, bodyParams,
request) to use c.get('bodyParams') ?? {} and c.get('queryParams') ?? {} so
bodyParams and queryParams are always objects even if c.get(...) returns
undefined, keeping the existing fields (e.g., requestIp: c.get('remoteAddress')
and urlParams: req.param()) unchanged.

@ricardogarim ricardogarim force-pushed the chore/router-improvements branch 2 times, most recently from 3ad9b41 to 5ffad11 Compare January 23, 2026 21:36
@d-gubert d-gubert removed the request for review from a team January 27, 2026 18:47
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@apps/meteor/app/api/server/middlewares/logger.ts`:
- Around line 23-25: The logger middleware currently uses redact: ['password']
which won't match nested fields inside the request body; update the redact
configuration to target the nested payload key (use redact:
['payload.password']) in the logger/middleware configuration so that any
password inside the payload object is properly redacted; locate the redact
property in the logger middleware file
(apps/meteor/app/api/server/middlewares/logger.ts) and replace the array entry
'password' with 'payload.password'.

In `@packages/http-router/src/Router.ts`:
- Around line 165-168: parseBodyParams currently returns form entries directly
from request.raw.clone().formData() (in Router.ts) so payload fields sent as
application/x-www-form-urlencoded remain JSON strings; update the code in
parseBodyParams to detect a "payload" entry, attempt to JSON.parse(payload) and
merge/replace its parsed object into the returned params (e.g., const parsed =
JSON.parse(payload) and return { ...otherParams, ...parsed }), and ensure
parsing is wrapped in try/catch so malformed JSON falls back to the original
string; this change will satisfy the incoming-integrations test that sends
payload=JSON.stringify(payload) and allow processWebhookMessage to receive
unwrapped fields like msg/text.
🧹 Nitpick comments (1)
apps/meteor/server/lib/logger/logPayloads.ts (1)

34-39: JSON parse failure returns { payload: null } instead of null.

When JSON parsing fails, the function returns { payload: null }, which will spread into the log object as payload: null. This differs from the disabled case (line 28) which returns null and spreads to nothing. Consider returning null on parse failure to avoid logging a payload: null field for unparseable bodies.

🔧 Suggested fix
 			return {
 				payload: await request.raw
 					.clone()
 					.json()
-					.catch(() => null),
+					.catch(() => undefined),
 			};

Or alternatively, to match the disabled behavior:

-			return {
-				payload: await request.raw
-					.clone()
-					.json()
-					.catch(() => null),
-			};
+			try {
+				return { payload: await request.raw.clone().json() };
+			} catch {
+				return null;
+			}

@d-gubert d-gubert force-pushed the chore/improve-livechat-customfield-endpoint branch from e8e1db7 to 08e89d1 Compare January 27, 2026 20:49
@d-gubert d-gubert force-pushed the chore/router-improvements branch from 20ecbe8 to 00a2cbe Compare January 31, 2026 20:22
@d-gubert d-gubert requested review from a team as code owners January 31, 2026 20:22
@d-gubert d-gubert changed the base branch from chore/improve-livechat-customfield-endpoint to develop January 31, 2026 20:39
@d-gubert d-gubert removed request for a team January 31, 2026 20:39
@d-gubert d-gubert force-pushed the chore/router-improvements branch from 00a2cbe to d9239a2 Compare January 31, 2026 21:22
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@apps/meteor/server/lib/logger/logPayloads.ts`:
- Around line 26-39: getRestPayload currently only catches errors from
request.raw.clone().json()'s .json() call but not from request.raw.clone()
itself, which can throw if the body was already consumed; modify the async
branch in getRestPayload to wrap the entire clone+json sequence in a try/catch
(surround request.raw.clone().json() with try) and on any error return {
payload: null } (or { payload: '[multipart/form-data]' } earlier), ensuring
clone failures are handled and logging remains best‑effort.
🧹 Nitpick comments (1)
packages/http-router/src/Router.ts (1)

171-174: Consider debug-level logging for parse failures.

The silent catch makes debugging harder when requests fail unexpectedly. While the design allows endpoints to handle their own parsing, a debug-level log would help trace issues without affecting behavior.

🔧 Optional: Add debug logging
-		} catch {
-			// No problem if there is error, just means the endpoint is going to have to parse the body itself if necessary
+		} catch (e) {
+			logger.debug({ msg: 'Body parsing skipped, endpoint may handle manually', err: e });
 			return {};
 		}

@d-gubert d-gubert force-pushed the chore/router-improvements branch 2 times, most recently from 5533271 to c6119ad Compare February 4, 2026 11:57
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 3 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="packages/rest-typings/src/v1/omnichannel.ts">

<violation number="1" location="packages/rest-typings/src/v1/omnichannel.ts:4503">
P2: The type for `customFieldId` no longer matches the schema: the schema allows `null` and omission, but the type now requires a key and disallows `null`. This will reject valid inputs in typing/compile-time usage. Consider making the property optional and allowing `null` to align with the schema.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@d-gubert d-gubert force-pushed the chore/router-improvements branch from 34a3e12 to ea2565c Compare February 5, 2026 12:16
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@apps/meteor/app/livechat/server/api/v1/customField.ts`:
- Around line 114-123: The validation order is inverted: the regex check for
customFieldId should run before querying the DB so format errors return
immediately; update the block that uses customFieldId (the conditional
containing LivechatCustomField.findOneById and the /^[0-9a-zA-Z-_]+$/ test) to
first test the regex and return API.v1.failure('Invalid custom field name...')
on failure, then call LivechatCustomField.findOneById(customFieldId) and return
API.v1.failure('Custom Field Not found') if that lookup returns null.

@d-gubert d-gubert added the stat: QA assured Means it has been tested and approved by a company insider label Feb 6, 2026
@dionisio-bot dionisio-bot bot added the stat: ready to merge PR tested and approved waiting for merge label Feb 6, 2026
@kodiakhq kodiakhq bot merged commit ac9065f into develop Feb 6, 2026
79 of 81 checks passed
@kodiakhq kodiakhq bot deleted the chore/router-improvements branch February 6, 2026 00:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stat: QA assured Means it has been tested and approved by a company insider stat: ready to merge PR tested and approved waiting for merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants